/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.debugger.jpda;
import java.util.ResourceBundle;
import java.util.List;
import java.util.LinkedList;
import java.text.MessageFormat;
import javax.swing.SwingUtilities;
import javax.swing.JComponent;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.MethodEntryRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.event.BreakpointEvent;
import com.sun.jdi.event.LocatableEvent;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.EventIterator;
import com.sun.jdi.event.StepEvent;
import org.openide.TopManager;
import org.openide.filesystems.FileObject;
import org.openide.text.Line;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.openide.util.NbBundle;
import org.netbeans.modules.debugger.jpda.util.*;
import org.netbeans.modules.debugger.support.MethodBreakpointEvent;
import org.netbeans.modules.debugger.support.StopEvent;
import org.netbeans.modules.debugger.support.PrintAction;
import org.netbeans.modules.debugger.support.StopAction;
import org.netbeans.modules.debugger.support.AbstractVariable;
import org.netbeans.modules.debugger.support.AbstractThread;
import org.netbeans.modules.debugger.support.CoreBreakpoint;
import org.netbeans.modules.debugger.support.CallStackFrame;
/**
* Implementation of breakpoint on method.
*
* @author Jan Jancura
*/
public class MethodBreakpoint extends MethodBreakpointEvent implements Executor, StopEvent {
// static ....................................................................................
/** Property name constant. */
public static final String PROP_ALL_METHODS = "allMethods"; // NOI18N
// variables ....................................................................................
/** Thread which stops on this breakpoint. */
private transient ThreadReference thread;
/** Stores all EventRequests produced by this Event. */
private Requestor requestor;
private ReferenceType tryClass;
/** Curent method lines. */
private LinkedList lines = new LinkedList ();
private Line[] linesArray;
private boolean allMethods = false;
// Event impl ......................................................................................
/**
* Returns the new instance of Breakpoint.Event.
*/
public CoreBreakpoint.Event getNewInstance () {
return new MethodBreakpoint ();
}
/**
* Sets breakpoint with specified properties.
*/
public boolean set () {
//S ystem.out.println ();
//S ystem.out.println (" " + this + ":set TRY in " + getDebugger () ); // NOI18N
JPDADebugger debugger = (JPDADebugger) getDebugger ();
if (debugger.virtualMachine == null) return false;
if ((getClassName () == null) || (getClassName ().trim ().length () < 1)) return false;
if ( (!getAllMethods ()) &&
( (getMethodName () == null) ||
(getMethodName ().trim ().length () < 1)
)
) return false;
if (requestor == null) requestor = new Requestor (debugger.requestManager);
try {
requestor.removeRequests ();
if (allMethods) {
MethodEntryRequest mer = debugger.requestManager.createMethodEntryRequest ();
mer.addClassFilter (getClassName ());
mer.setSuspendPolicy (MethodEntryRequest.SUSPEND_ALL);
debugger.operator.register (mer, this);
requestor.add (mer);
mer.enable ();
//S ystem.out.println ();
//S ystem.out.println (" " + this + ":set ALL METHODS " + getClassName ()); // NOI18N
return true;
}
// For unloaded class
//S ystem.out.println ();
//S ystem.out.println (" " + this + ":set class br. " + getClassName ()); // NOI18N
ClassPrepareRequest cpr = debugger.requestManager.createClassPrepareRequest ();
cpr.addClassFilter (getClassName ()); // NOI18N
cpr.setSuspendPolicy (BreakpointRequest.SUSPEND_ALL);
debugger.operator.register (cpr, this);
requestor.add (cpr);
cpr.enable ();
List l = debugger.virtualMachine.classesByName (getClassName ());
if (l.size () == 0) return false;
// Known classes
//S ystem.out.println ();
//S ystem.out.println (" " + this + ":set " + l.size () + " are loaded"); // NOI18N
int i, k = l.size ();
boolean set = false;
for (i = 0; i < k; i++)
if (set ((ReferenceType) l.get (i)))
set = true;
return set;
} catch (VMDisconnectedException e) {
}
return false;
}
/**
* Removes breakpoint.
*/
public void remove () { //S ystem.out.println ("MethodBreakpoint.remove " + this); // NOI18N
//S ystem.out.println (); // NOI18N
//S ystem.out.println (" " + this + ":remove "); // NOI18N
if (requestor != null)
requestor.removeRequests ();
linesArray = null;
lines = new LinkedList ();
}
/**
* Returns specific properties of this event.
*/
public Node.Property[] getProperties () {
ResourceBundle bundle = NbBundle.getBundle (VariableBreakpoint.class);
return new Node.Property[] {
new PropertySupport.ReadWrite (
CoreBreakpoint.PROP_CLASS_NAME,
String.class,
bundle.getString ("PROP_breakpoint_class_name"),
bundle.getString ("HINT_breakpoint_class_name")
) {
public Object getValue () {
return getClassName ();
}
public void setValue (Object val) throws IllegalArgumentException {
try {
setClassName (((String)val).trim ());
} catch (ClassCastException e) {
throw new IllegalArgumentException ();
}
}
},
new PropertySupport.ReadWrite (
CoreBreakpoint.PROP_METHOD_NAME,
String.class,
bundle.getString ("PROP_breakpoint_method_name"),
bundle.getString ("HINT_breakpoint_method_name")
) {
public Object getValue () throws IllegalArgumentException {
return getMethodName ();
}
public void setValue (Object val) throws IllegalArgumentException {
try {
setMethodName (((String)val).trim ());
} catch (ClassCastException e) {
throw new IllegalArgumentException ();
}
}
},
new PropertySupport.ReadWrite (
PROP_ALL_METHODS,
Boolean.TYPE,
bundle.getString ("PROP_breakpoint_all_methods"),
bundle.getString ("HINT_breakpoint_all_methods")
) {
public Object getValue () throws IllegalArgumentException {
return new Boolean (getAllMethods ());
}
public void setValue (Object val) throws IllegalArgumentException {
try {
setAllMethods (((Boolean) val).booleanValue ());
} catch (ClassCastException e) {
throw new IllegalArgumentException ();
}
}
}
};
}
/**
* Returns line of breakpoint.
*/
public Line[] getLines () {
if (linesArray != null) return linesArray;
if (lines.size () == 0) return null;
linesArray = (Line[]) lines.toArray (new Line [lines.size ()]); //S ystem.out.println("MethodBreakpoint.getLines : " + lines.size ()); // NOI18N
return linesArray;
}
/**
* Returns customizer visual component.
*/
public JComponent getCustomizer () {
return new MethodBreakpointPanel (this);
}
/**
* Returns display name of this instance of event. It will be used
* as the name of the breakpoint.
*/
public String getDisplayName () {
if (getAllMethods ())
return new MessageFormat (
NbBundle.getBundle (MethodBreakpoint.class).getString ("CTL_All_method_event_name")
).format (new Object[] {getClassName ()});
else
return new MessageFormat (
NbBundle.getBundle (MethodBreakpoint.class).getString ("CTL_Method_event_name")
).format (new Object[] {getClassName (), getMethodName ()});
}
/**
* Returns actions available specially for this version of event.
*/
public CoreBreakpoint.Action[] getBreakpointActions () {
CoreBreakpoint.Action[] myActions = new CoreBreakpoint.Action[] {
new StopAction (),
new PrintAction (PrintAction.BREAKPOINT_METHOD_TEXT),
};
CoreBreakpoint.Action[] actions = new CoreBreakpoint.Action [super.getBreakpointActions ().length + myActions.length];
System.arraycopy (super.getBreakpointActions (), 0, actions, 0, super.getBreakpointActions ().length);
System.arraycopy (myActions, 0, actions, super.getBreakpointActions ().length, myActions.length);
return actions;
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractThread getThread () {
if (thread == null) return null;
JPDADebugger debugger = (JPDADebugger) getDebugger ();
return debugger.threadManager.getThread (thread);
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public CallStackFrame[] getCallStack () {
return getThread ().getCallStack ();
}
/**
* Aditional ifno about debugger state when this event occures.
* If event do not produce this type of info, null is returned.
*/
public AbstractVariable getVariable () {
return null;
/* try {
RemoteStackVariable rsv = thread.getCurrentFrame ().getLocalVariable ("this");
return new ToolsVariable (
(ToolsDebugger) getDebugger (),
rsv.getName (),
rsv.getValue (),
rsv.getType ().toString ()
);
} catch (Exception e) {
return null;
} */
}
// interface Executor .....................................................................
/**
* Executes breakpoint hit event.
*/
public void exec (com.sun.jdi.event.Event event) {
//S ystem.out.println ();
//S ystem.out.println (this + ":exec " + event); // NOI18N
if (event instanceof ClassPrepareEvent) {
tryClass = ((ClassPrepareEvent) event).referenceType ();
boolean v = set (tryClass);
if (v && !getBreakpoint ().isValid ()) setValid (true);
((JPDADebugger) getDebugger ()).operator.resume ();
return;
}
thread = ((LocatableEvent) event).thread ();
JPDADebugger debugger = (JPDADebugger) getDebugger ();
try {
if (thread.frame (0).location ().method ().isSynthetic ()) {
debugger.operator.resume ();
return;
}
}
catch (Exception e) {
}
if (debugger.resolveCanBeCurrent (thread))
return;
perform ();
}
// StopEvent impl ......................................................................................
/**
* Performs stop action.
*/
public void stop (boolean stop) {
((JPDADebugger) getDebugger ()).stop (stop, getThread ());
}
// other methods ......................................................................................
/**
*
*/
public boolean getAllMethods () {
return allMethods;
}
/**
*
*/
public void setAllMethods (boolean all) {
if (allMethods == all) return;
boolean old = allMethods;
allMethods = all;
firePropertyChange (PROP_ALL_METHODS, new Boolean (old), new Boolean (allMethods));
}
/**
* Sets breakpoint for given class.
*/
public boolean set (ReferenceType clazz) {
JPDADebugger debugger = (JPDADebugger) getDebugger ();
if (debugger.virtualMachine == null) return false;
if ( (!getAllMethods ()) &&
( (getMethodName () == null) ||
(getMethodName ().trim ().length () < 1)
)
) return false;
try {
List methods = clazz.methods ();
//S ystem.out.println (" " + this + ":set2 all methods numb. " +
// methods.size ()); // NOI18N
boolean ok = false;
int j, jj = methods.size ();
for (j = 0; j < jj; j++) {
Method method = (Method) methods.get (j);
if (!method.name ().equals (getMethodName ())) continue;
Location loc = method.location ();
if (loc == null) {
//S ystem.out.println (" " + this + ":set2 method " + method.name () +
// " :loc. : null"); // NOI18N
continue;
}
addLine (loc);
//S ystem.out.println (" " + this + ":set2 method " + method.name () + " :loc. : " + loc.lineNumber ()); // NOI18N
//removeRequests ();
BreakpointRequest br = debugger.requestManager.createBreakpointRequest (loc);
br.setSuspendPolicy (BreakpointRequest.SUSPEND_ALL);
debugger.operator.register (br, this);
requestor.add (br);
br.enable ();
ok = true;
//S ystem.out.println (" " + this + ":set2 method OK !!!!!!!"); // NOI18N
}
return ok;
} catch (Exception e) {
//S ystem.out.println (" " + this + ":set2 " + e); // NOI18N
}
return false;
}
/**
* Sets current method line.
*/
private void addLine (Location l) {
linesArray = null;
Line line = Utils.getLine (className, l.lineNumber ());
if (line != null)
lines.add (line);
}
public String toString () {
return "JPDAMethodBreakpoint " + getClassName () + "." + getMethodName (); // NOI18N
}
}
/*
* Log
* $
*/